/* 
 * Copyright (C) 2013, 2014 lex
 * All Rigth Reserved.
 *
 * file:	drivers/uart.c
 * history:	2013 Juy 5 created by lex
 */

#include "uart.h"
#include "stdarg.h"
#include "s3c2440.h"

void uart_init(int idx)
{
	int i;
	struct uart_dev *dev;

	dev = (struct uart_dev *)(UART_BASE_ADDR + idx * 0x4000);

	/* 
	 * uart line control 
	 */
	dev->lcr.data		= 0;
	dev->lcr.l.word_len	= 3;	/* 8 - bits */

	/* 
	 * uart control 
	 */
	dev->ccr.data		= 0;
	dev->ccr.c.rx_mode	= 1;	/* rx ->  polling or intrrupt */
	dev->ccr.c.tx_mode	= 1;	/* tx ->  polling or intrrupt */
	dev->ccr.c.tx_int_type	= 1;

	dev->fcr.data = 0;
	dev->mcr.data = 0;

	/* 
	 * set baud rate divisior 
	 */
	dev->brdiv = 26;

	for (i = 0; i < 100; i++)
		;

	return;
}

u8 uart_getc(int idx)
{
	struct uart_dev *dev;

	dev = (struct uart_dev *)(UART_BASE_ADDR + idx * 0x4000);

	while (!dev->trsr.tr.rx_ready)
		;
	return (dev->rbr.b.byte & 0xff);
}

void uart_putc(u8 ch, int idx)
{
	struct uart_dev *dev;

	dev = (struct uart_dev *)(UART_BASE_ADDR + idx * 0x4000);

	while (!dev->trsr.tr.tx_empty)
		;
	dev->tbr.b.byte = ch & 0xff;

	return;
}

void uart_puts(u8 *str, int idx)
{
	while (*str) {
		if (*str == '\n')
			uart_putc('\r', idx);
		uart_putc(*(str++), idx);
	}
}

void uart_printf(int idx, char *fmt, ...)
{
	char buf[NR_PRINT_CH_MAX];
	va_list arg;

	va_start(arg, fmt);
	vsnprintf(buf, NR_PRINT_CH_MAX, fmt, arg);
	va_end(arg);

	uart_puts((u8 *)buf, idx);

	return;
}

void printf_d(char *fmt, ...)
{
	char buf[NR_PRINT_CH_MAX];
	va_list arg;

	va_start(arg, fmt);
	vsnprintf(buf, NR_PRINT_CH_MAX, fmt, arg);
	va_end(arg);

	uart_puts((u8 *)buf, 0);

	return;
}


/* delay (ms) */
u8 uart_getc_timeout(int idx, u32 delay)
{
	struct uart_dev *dev;

	dev = (struct uart_dev *)(UART_BASE_ADDR + idx * 0x4000);

	while (!dev->trsr.tr.rx_ready && --delay)
		;

	return (dev->rbr.b.byte & 0xff);
}
